package geppetto.cat.alignments.output;


import geppetto.cat.alignments.Alignment;
import geppetto.cat.alignments.AlignmentEvaluator;
import geppetto.cat.alignments.AlignmentsSet;
import geppetto.cat.alignments.AlignmentEvaluator.Evaluation;
import geppetto.cat.corpus.BilingualCorpus;

import java.io.PrintStream;
import java.io.UnsupportedEncodingException;



public class AlignerOutputLatex {

	// Outputs a AlignmentSet an alignment by a time, of sentences of maxSize 
	
	public static void outputWithGoldPostLatex(AlignmentsSet alignments,
			AlignmentsSet golds, BilingualCorpus corpus, PrintStream out,
			int maxSize, String caption) throws UnsupportedEncodingException {
		
		printAlignmentCaption(out);
		for (int i = 0; i < alignments.size(); i++) {
			
			Alignment al = alignments.get(i);
			Alignment gold = golds.get(al.getSentenceNumber());
			
			if (al._foreignLen > maxSize || al._sourceLen > maxSize)
				continue;
			Evaluation eval = AlignmentEvaluator.evaluate(al, gold);
			outputWithGoldPostLatex(al, gold, corpus, out, " sentence Nr " + i + " P: " + eval.getPrecision() + " R: " + eval.getRecall() + " aer " + eval.getAER());
			out.println("\\clearpage\\pagebreak");
		}
	}
	
	public static void outputWithGoldPostLatex(AlignmentsSet alignments,
			AlignmentsSet golds, BilingualCorpus corpus, PrintStream out,
			int maxSize, String caption, String rules) throws UnsupportedEncodingException {
		
		printAlignmentCaption(out);
		String[] sets = rules.split(","); 
		for (String set : sets){
			int startIndex = 0;
			int endIndex = 0;
			if(set.contains("-")){
				String[] start_end = set.split("-");
				startIndex = Integer.parseInt(start_end[0]);
				endIndex = Integer.parseInt(start_end[1]);
			}
			else{
				startIndex = Integer.parseInt(set);
				endIndex = Integer.parseInt(set);
			}
			for (int i = startIndex; i <= endIndex; i++) {
				Alignment al = alignments.get(i);
				Alignment gold = golds.get(al.getSentenceNumber());
				
				if (al._foreignLen > maxSize || al._sourceLen > maxSize){
					continue;
				}
				System.out.println(i);
				Evaluation eval = AlignmentEvaluator.evaluate(al, gold);
				outputWithGoldPostLatex(al, gold, corpus, out, " sentence Nr " + i + " P: " + eval.getPrecision() + " R: " + eval.getRecall() + " aer " + eval.getAER());
				out.println("\\clearpage\\pagebreak");
			}
		}
		
	} 
	
	// outputs an alignment by a time, of sentences of maxSize 
	public static void outputWithGoldPostLatex(AlignmentsSet alignments, int i,
			AlignmentsSet golds, BilingualCorpus corpus, PrintStream out,
			int maxSize, String caption) throws UnsupportedEncodingException {
		
		Alignment al = alignments.get(i);
		Alignment gold = golds.get(al.getSentenceNumber());
			
		if (al._foreignLen > maxSize || al._sourceLen > maxSize){
			return;
		}

		outputWithGoldPostLatex(al, gold, corpus, out, " Alignments for sentence number " + (i + 1));
		out.println("\\clearpage\\pagebreak");
	}
	
	//Converts the probability into a circle width to be used 
	//on printing
	public static double convertPost(double number) {
		if (number < 0.01) {
			return 0;
		} else if (number < 0.05) {
			return 0.5;
		} else if (number < 0.1) {
			return 1;
		} else if (number < 0.2) {
			return 2;
		} else if (number < 0.4) {
			return 4;
		} else if (number < 0.5) {
			return 5;
		} else if (number < 0.6) {
			return 6;
		} else if (number < 0.7) {
			return 7;
		} else if (number < 0.8) {
			return 8;
		} else if (number < 0.9) {
			return 9;
		} else if (number < 0.95) {
			return 10;
		} else if (number < 1.001) {
			return 11;
		} else {
			System.out.println("Errro post bigger than 1");
			System.exit(-1);
		}
		return 0;
	}

	//Converts special characters
	public static String outputLatexString(String source)
			throws UnsupportedEncodingException {
		if (source.equals("$")) {
			return "\\$";
		} else if (source.equals("#")) {
			return "\\#";
		} else if (source.equals("%")) {
			return "\\%";
		} else if (source.equals("&")) {
			return "\\&";
		} else if (source.equals("_")) {
			return "\\_";
		} else if (source.equals("[")) {
			return "\\[";
		} else if (source.equals("]")) {
			return "\\]";
		} else if (source.equals("<<")) {
			return "\\<\\<]";
		} else if (source.equals(">>")) {
			return "\\>\\>]";
		} else {
			return source;
		}
	}

	//Print an entry for a given source word , with posterior values and gold
	//alignments
	public static void printEntrieOnlyPostGold(PrintStream out, int entry,
			int wordSize, Alignment alignment, Alignment gold,
			BilingualCorpus corpus, int sentenceNumber, byte sentenceSource)
			throws UnsupportedEncodingException {
		for (int fi = 0; fi < wordSize + 1; fi++) {
			if (fi == 0) {
				out.print("\\aln{" + entry + "}" + "&");
			} else {
				if (gold.isPossible(entry, fi - 1)) {
					out.print("\\npale{"
							+ convertPost(alignment._posteriors[entry][fi - 1])
							+ "} & ");
				} else if (gold.isSure(entry, fi - 1)) {
					out.print("\\nsale{"
							+ convertPost(alignment._posteriors[entry][fi - 1])
							+ "} & ");
				} else {
					out.print("\\nepty{"
							+ convertPost(alignment._posteriors[entry][fi - 1])
							+ "} & ");
				}
			}
		}
	}

	public static void printEntrieNoPost(PrintStream out, int entry,
			int wordSize, Alignment alignment, Alignment gold,
			BilingualCorpus corpus, int sentenceNumber, byte sentenceSource)
			throws UnsupportedEncodingException {
		for (int fi = 0; fi < wordSize + 1; fi++) {
			if (fi == 0) {
				out.print("\\aln{" + entry + "}" + "&");
			} else {
				if (alignment.hasPosition(entry, fi - 1)) {
					if (gold.isPossible(entry, fi - 1)) {
						out.print("\\npalf{" + convertPost(1) + "} & ");
					} else if (gold.isSure(entry, fi - 1)) {
						out.print("\\nsalf{" + convertPost(1) + "} & ");
					} else {
						out.print("\\nnalf{" + convertPost(1) + "} & ");
					}
				} else {
					if (gold.isPossible(entry, fi - 1)) {
						out.print("\\npale{" + convertPost(0) + "} & ");
					} else if (gold.isSure(entry, fi - 1)) {
						out.print("\\nsale{" + convertPost(0) + "} & ");
					} else {
						out.print("\\nepty{" + convertPost(0) + "} & ");
					}
				}
			}
		}
		out.print("\\nepty{" + convertPost(0) + "} &");
	}

	
	
	public static void printEntriePost(PrintStream out, int entry, int wordSize,
			Alignment alignment, Alignment gold, BilingualCorpus corpus,
			int sentenceNumber, byte sentenceSource)
			throws UnsupportedEncodingException {
		for (int fi = 0; fi < wordSize + 1; fi++) {
			if (fi == 0) {
				out.print("\\aln{" + entry + "}" + "&");
			} else {
					if (gold.isPossible(entry, fi - 1)) {
						out
								.print("\\possible{"
										+ convertPost(alignment._posteriors[entry][fi - 1])
										+ "}{"+"blue"+"} & ");
					} else if (gold.isSure(entry, fi - 1)) {
						out
								.print("\\sure{"
										+ convertPost(alignment._posteriors[entry][fi - 1])
										+ "}{"+"blue"+"} & ");
					} else {
						out
								.print("\\none{"
										+ convertPost(alignment._posteriors[entry][fi - 1])
										+ "}{"+"blue"+"} & ");
					}
				}
			}
	}
	
	public static void printEntriePost(PrintStream out, int entry, int wordSize,
			Alignment alignment, Alignment toCompare, Alignment gold, BilingualCorpus corpus,
			int sentenceNumber, byte sentenceSource)
			throws UnsupportedEncodingException {
		for (int fi = 0; fi < wordSize + 1; fi++) {
			if (fi == 0) {
				out.print("\\aln{" + entry + "}" + "&");
			} else {
					String color;
					if(alignment._posteriors[entry][fi - 1] < toCompare._posteriors[entry][fi - 1]){
						 color = "red";
					}else if(alignment._posteriors[entry][fi - 1] > toCompare._posteriors[entry][fi - 1]){
						color = "green";
					}else{
						color = "blue";
					}
					if (gold.isPossible(entry, fi - 1)) {
						out
								.print("\\possible{"
										+ convertPost(alignment._posteriors[entry][fi - 1])
										+ "}{"+color+"} & ");
					} else if (gold.isSure(entry, fi - 1)) {
						out
								.print("\\sure{"
										+ convertPost(alignment._posteriors[entry][fi - 1])
										+ "}{"+color+"} & ");
					} else {
						out
								.print("\\none{"
										+ convertPost(alignment._posteriors[entry][fi - 1])
										+ "}{"+color+"} & ");
					}
			}
		}
	}
	
	public static void printEntrie(PrintStream out, int entry, int wordSize,
			Alignment alignment, Alignment gold, BilingualCorpus corpus,
			int sentenceNumber, byte sentenceSource)
			throws UnsupportedEncodingException {
		for (int fi = 0; fi < wordSize + 1; fi++) {
			if (fi == 0) {
				out.print("\\aln{" + entry + "}" + "&");
			} else {
				if (alignment.hasPosition(entry, fi - 1)) {
					if (gold.isPossible(entry, fi - 1)) {
						out
								.print("\\npalf{"
										+ convertPost(alignment._posteriors[entry][fi - 1])
										+ "} & ");
					} else if (gold.isSure(entry, fi - 1)) {
						out
								.print("\\nsalf{"
										+ convertPost(alignment._posteriors[entry][fi - 1])
										+ "} & ");
					} else {
						out
								.print("\\nnalf{"
										+ convertPost(alignment._posteriors[entry][fi - 1])
										+ "} & ");
						}
				} else {
					if (gold.isPossible(entry, fi - 1)) {
						out
								.print("\\npale{"
										+ convertPost(alignment._posteriors[entry][fi - 1])
										+ "} & ");
					} else if (gold.isSure(entry, fi - 1)) {
						out
								.print("\\nsale{"
										+ convertPost(alignment._posteriors[entry][fi - 1])
										+ "} & ");
					} else {
						out
								.print("\\nepty{"
										+ convertPost(alignment._posteriors[entry][fi - 1])
										+ "} & ");
					}
				}
			}
		}
	}

	public static void printEntrieOnlyPostGoldBack(PrintStream out, int entry,
			int wordSize, Alignment alignment, Alignment gold,
			BilingualCorpus corpus, int sentenceNumber, byte sentenceSource)
			throws UnsupportedEncodingException {
		double empty = 1;
		for (int fi = 0; fi < wordSize + 1; fi++) {
			if (fi == 0) {
				out.print("\\aln{" + entry + "}" + "&");
			} else {
				empty -= alignment._posteriors[fi - 1][entry];
				if (gold.isPossible(entry, fi - 1)) {
					out.print("\\npale{"
							+ convertPost(alignment._posteriors[fi - 1][entry])
							+ "} & ");
				} else if (gold.isSure(entry, fi - 1)) {
					out.print("\\nsale{"
							+ convertPost(alignment._posteriors[fi - 1][entry])
							+ "} & ");
				} else {
					out.print("\\nepty{"
							+ convertPost(alignment._posteriors[fi - 1][entry])
							+ "} & ");
				}
			}
		}
		out.print("\\nepty{" + convertPost(empty) + "} &");
	}

	public static void printBackwardEntrie(PrintStream out, int entry,
			int wordSize, Alignment alignment, Alignment gold,
			BilingualCorpus corpus, int sentenceNumber, byte sentenceSource)
			throws UnsupportedEncodingException {
		double empty = 1;
		for (int fi = 0; fi < wordSize + 1; fi++) {
			if (fi == 0) {
				out.print("\\aln{" + entry + "}" + "&");
			} else {
				if (alignment.hasPosition(fi - 1, entry)) {
					if (gold.isPossible(entry, fi - 1)) {
						empty -= alignment._posteriors[fi - 1][entry];
						out
								.print("\\npalf{"
										+ convertPost(alignment._posteriors[fi - 1][entry])
										+ "} & ");
					} else if (gold.isSure(entry, fi - 1)) {
						empty -= alignment._posteriors[fi - 1][entry];
						out
								.print("\\nsalf{"
										+ convertPost(alignment._posteriors[fi - 1][entry])
										+ "} & ");
					} else {
						empty -= alignment._posteriors[fi - 1][entry];
						out
								.print("\\nnalf{"
										+ convertPost(alignment._posteriors[fi - 1][entry])
										+ "} & ");
					}
				} else {
					if (gold.isPossible(entry, fi - 1)) {
						empty -= alignment._posteriors[fi - 1][entry];
						out
								.print("\\npale{"
										+ convertPost(alignment._posteriors[fi - 1][entry])
										+ "} & ");
					} else if (gold.isSure(entry, fi - 1)) {
						empty -= alignment._posteriors[fi - 1][entry];
						out
								.print("\\nsale{"
										+ convertPost(alignment._posteriors[fi - 1][entry])
										+ "} & ");
					} else {
						empty -= alignment._posteriors[fi - 1][entry];
						out
								.print("\\nepty{"
										+ convertPost(alignment._posteriors[fi - 1][entry])
										+ "} & ");
					}
				}
			}
		}
		out.print("\\nepty{" + convertPost(empty) + "} &");
	}

	
	public static void printBackwardEntriePost(PrintStream out, int entry,
			int wordSize, Alignment alignment, Alignment gold,
			BilingualCorpus corpus, int sentenceNumber, byte sentenceSource)
			throws UnsupportedEncodingException {
		double empty = 1;
		for (int fi = 0; fi < wordSize + 1; fi++) {
			if (fi == 0) {
				out.print("\\aln{" + entry + "}" + "&");
			} else {		
				if (gold.isPossible(entry, fi - 1)) {
					empty -= alignment._posteriors[fi - 1][entry];
					out
					.print("\\possible{"
							+ convertPost(alignment._posteriors[fi - 1][entry])
							+ "}{"+"blue"+"} & ");
					} else if (gold.isSure(entry, fi - 1)) {
						empty -= alignment._posteriors[fi - 1][entry];
						out
								.print("\\sure{"
										+ convertPost(alignment._posteriors[fi - 1][entry])
										+ "}{"+"blue"+"} & ");
					} else {
						empty -= alignment._posteriors[fi - 1][entry];
						out
								.print("\\none{"
										+ convertPost(alignment._posteriors[fi - 1][entry])
										+ "}{"+"blue"+"} & ");
					}
				}
		}
		//out.print("\\nepty{" + convertPost(empty) + "} &");
	}
	
	
	public static void printBackwardEntriePost(PrintStream out, int entry,
			int wordSize, Alignment alignment, Alignment toCompare,
			Alignment gold,
			BilingualCorpus corpus, int sentenceNumber, byte sentenceSource)
			throws UnsupportedEncodingException {
		double empty = 1;
		for (int fi = 0; fi < wordSize + 1; fi++) {
			if (fi == 0) {
				out.print("\\aln{" + entry + "}" + "&");
			} else {	
				String color;
				if(alignment._posteriors[fi - 1][entry] < toCompare._posteriors[fi - 1][entry]){
					 color = "red";
				}else if(alignment._posteriors[fi - 1][entry] > toCompare._posteriors[fi - 1][entry]){
					color = "green";
				}else{
					color = "blue";
				}
				if (gold.isPossible(entry, fi - 1)) {
					empty -= alignment._posteriors[fi - 1][entry];
					out.print("\\possible{"
							+ convertPost(alignment._posteriors[fi - 1][entry])
							+ "}{"+color+"} & ");
				} else if (gold.isSure(entry, fi - 1)) {
					empty -= alignment._posteriors[fi - 1][entry];
						out
								.print("\\sure{"
										+ convertPost(alignment._posteriors[fi - 1][entry])
										+ "}{"+color+"} & ");
					} else {
						empty -= alignment._posteriors[fi - 1][entry];
						out
								.print("\\none{"
										+ convertPost(alignment._posteriors[fi - 1][entry])
										+ "}{"+color+"} & ");
					}
			}
		}
		//out.print("\\nepty{" + convertPost(empty) + "} &");
	}

	
	public static void outputWithGoldPostLatex(Alignment alignment,
			Alignment gold, BilingualCorpus corpus, PrintStream out,
			String caption) throws UnsupportedEncodingException {
		int sentenceNumber = alignment.getSentenceNumber();
		byte sourceSentence = alignment.getSentenceSource();
		// out.println("Gold Alignment for Sentence " +
		// alignment._sentenceNumber);
		int foreignSize = alignment.getForeignLenght();
		int sourceSize = alignment.getSourceLenght();
		printBeginTable(out, foreignSize);
		// Line with number
		printLineWithNumber(out, foreignSize);
		out.println(" \\\\");
		out.println();
		// Print each entry
		for (int si = 0; si < sourceSize; si++) {
			printEntrie(out, si, foreignSize, alignment, gold, corpus,
					sentenceNumber, sourceSentence);
			String word = outputLatexString(corpus.getSourceWord(
					sentenceNumber, sourceSentence, si));
			if (corpus._sourceWordsCounts.get(corpus.getSourceWordId(
					sentenceNumber, sourceSentence, si)) < 5) {
				out.print("\\alsw{\\color{red}{" + word + "}}\\\\");
			} else if (corpus._sourceWordsCounts.get(corpus.getSourceWordId(
					sentenceNumber, sourceSentence, si)) < 10) {
				out.print("\\alsw{\\color{green}{" + word + "}}\\\\");
			} else if (corpus._sourceWordsCounts.get(corpus.getSourceWordId(
					sentenceNumber, sourceSentence, si)) < 20) {
				out.print("\\alsw{\\color{yellow}{" + word + "}}\\\\");
			} else {
				out.print("\\alsw{" + word + "}\\\\");
			}
			out.println();
		}
		printBottomLine(out, foreignSize, sentenceNumber, sourceSentence,
				corpus);
		out.println(" \\\\");
		out.println();
		printEndTable(out, caption);
	}

	public static void outputPostLatex(Alignment al, Alignment al2,
			Alignment al3, Alignment gold, BilingualCorpus corpus,
			PrintStream out, String caption)
			throws UnsupportedEncodingException {
		int sentenceNumber = al.getSentenceNumber();
		byte sourceSentence = al.getSentenceSource();
		// out.println("Gold Alignment for Sentence " +
		// alignment._sentenceNumber);
		int foreignSize = al.getForeignLenght();
		int sourceSize = al.getSourceLenght();
		printBeginTable(out, foreignSize);
		// Line with number
		printLineWithNumber(out, foreignSize);
		out.println(" \\\\");
		// Print each entry
		for (int si = 0; si < sourceSize; si++) {
			printEntrieOnlyPostGold(out, si, foreignSize, al, gold, corpus,
					sentenceNumber, sourceSentence);
			outputSourceWord(out, corpus, sentenceNumber, sourceSentence, si);
		}
		printLineWithNumber(out, foreignSize);
		out.println(" \\\\");
		for (int si = 0; si < sourceSize; si++) {
			printEntrieOnlyPostGold(out, si, foreignSize, al2, gold, corpus,
					sentenceNumber, sourceSentence);
			outputSourceWord(out, corpus, sentenceNumber, sourceSentence, si);
		}
		printLineWithNumber(out, foreignSize);
		out.println(" \\\\");
		for (int si = 0; si < sourceSize; si++) {
			printEntrieOnlyPostGold(out, si, foreignSize, al3, gold, corpus,
					sentenceNumber, sourceSentence);
			outputSourceWord(out, corpus, sentenceNumber, sourceSentence, si);
		}
		printBottomLine(out, foreignSize, sentenceNumber, sourceSentence,
				corpus);
		out.println(" \\\\");
		printEndTable(out, caption);
	}

	public static void outputPostLatexBoth(Alignment al, Alignment alb,
			Alignment al2, Alignment al2b, Alignment al3, Alignment al3b,
			Alignment gold, Alignment goldb, BilingualCorpus corpus,
			PrintStream out, String caption)
			throws UnsupportedEncodingException {
		int sentenceNumber = al.getSentenceNumber();
		byte sourceSentence = al.getSentenceSource();
		// out.println("Gold Alignment for Sentence " +
		// alignment._sentenceNumber);
		int foreignSize = al.getForeignLenght();
		int sourceSize = al.getSourceLenght();
		printBeginTable(out, foreignSize * 2 + 3);
		// Line with number
		printLineWithNumber(out, foreignSize);
		printLineWithNumber(out, foreignSize);
		out.println(" \\\\");
		// Print each entry
		for (int si = 0; si < sourceSize; si++) {
			printEntrieOnlyPostGold(out, si, foreignSize, al, gold, corpus,
					sentenceNumber, sourceSentence);
			printEntrieOnlyPostGoldBack(out, si, foreignSize, alb, gold,
					corpus, sentenceNumber, sourceSentence);
			outputSourceWord(out, corpus, sentenceNumber, sourceSentence, si);
		}
		printLineWithNumber(out, foreignSize);
		printLineWithNumber(out, foreignSize);
		out.println(" \\\\");
		for (int si = 0; si < sourceSize; si++) {
			printEntrieOnlyPostGold(out, si, foreignSize, al2, gold, corpus,
					sentenceNumber, sourceSentence);
			printEntrieOnlyPostGoldBack(out, si, foreignSize, al2b, gold,
					corpus, sentenceNumber, sourceSentence);
			outputSourceWord(out, corpus, sentenceNumber, sourceSentence, si);
		}
		printLineWithNumber(out, foreignSize);
		printLineWithNumber(out, foreignSize);
		out.println(" \\\\");
		for (int si = 0; si < sourceSize; si++) {
			printEntrieOnlyPostGold(out, si, foreignSize, al3, gold, corpus,
					sentenceNumber, sourceSentence);
			printEntrieOnlyPostGoldBack(out, si, foreignSize, al3b, gold,
					corpus, sentenceNumber, sourceSentence);
			outputSourceWord(out, corpus, sentenceNumber, sourceSentence, si);
		}
		printBottomLine(out, foreignSize, sentenceNumber, sourceSentence,
				corpus);
		printBottomLine(out, foreignSize, sentenceNumber, sourceSentence,
				corpus);
		out.println(" \\\\");
		printEndTable(out, caption);
	}

	public static void outputWithGoldPostLatexForwardAndBackward(
			Alignment forward, Alignment backward, Alignment gold,
			BilingualCorpus corpus, PrintStream out, String caption)
			throws UnsupportedEncodingException {
		int sentenceNumber = forward.getSentenceNumber();
		byte sourceSentence = forward.getSentenceSource();
		// out.println("Gold Alignment for Sentence " +
		// alignment._sentenceNumber);
		int foreignSize = forward.getForeignLenght();
		int sourceSize = forward.getSourceLenght();
		printBeginTable(out, foreignSize * 2 + 3);
		// Line with number

		printLineWithNumber(out, foreignSize);
		printLineWithNumber(out, foreignSize);
		out.println(" \\\\");
		// Print each entry
		for (int si = 0; si < sourceSize; si++) {
			printEntrie(out, si, foreignSize, forward, gold, corpus,
					sentenceNumber, sourceSentence);
			printBackwardEntrie(out, si, foreignSize, backward, gold, corpus,
					sentenceNumber, sourceSentence);
			out.println("\\alsw{"
					+ outputLatexString(corpus.getSourceWord(sentenceNumber,
							sourceSentence, si)) + "}\\\\");
		}
		printBottomLine(out, foreignSize, sentenceNumber, sourceSentence,
				corpus);
		printBottomLine(out, foreignSize, sentenceNumber, sourceSentence,
				corpus);
		out.println(" \\\\");
		printEndTable(out, caption);
	}
	
	public static void outputWithGoldPostLatexForwardBackwardInterGrow(
			Alignment forward, Alignment backward, Alignment inter,
			Alignment grow, Alignment gold, BilingualCorpus corpus,
			PrintStream out, String caption)
			throws UnsupportedEncodingException {
		int sentenceNumber = forward.getSentenceNumber();
		byte sourceSentence = forward.getSentenceSource();
		// out.println("Gold Alignment for Sentence " +
		// alignment._sentenceNumber);
		int foreignSize = forward.getForeignLenght();
		int sourceSize = forward.getSourceLenght();
		printBeginTable(out, foreignSize * 2 + 3);
		// Line with number

		printLineWithNumber(out, foreignSize);
		printLineWithNumber(out, foreignSize);
		out.println(" \\\\");
		// Print each entry
		for (int si = 0; si < sourceSize; si++) {
			printEntrie(out, si, foreignSize, forward, gold, corpus,
					sentenceNumber, sourceSentence);
			printBackwardEntrie(out, si, foreignSize, backward, gold, corpus,
					sentenceNumber, sourceSentence);
			out.println("\\alsw{"
					+ outputLatexString(corpus.getSourceWord(sentenceNumber,
							sourceSentence, si)) + "}\\\\");
		}
		printLineWithNumber(out, foreignSize);
		printLineWithNumber(out, foreignSize);
		out.println(" \\\\");
		for (int si = 0; si < sourceSize; si++) {
			printEntrieNoPost(out, si, foreignSize, inter, gold, corpus,
					sentenceNumber, sourceSentence);
			printEntrieNoPost(out, si, foreignSize, grow, gold, corpus,
					sentenceNumber, sourceSentence);
			out.println("\\alsw{"
					+ outputLatexString(corpus.getSourceWord(sentenceNumber,
							sourceSentence, si)) + "}\\\\");
		}
		printBottomLine(out, foreignSize, sentenceNumber, sourceSentence,
				corpus);
		printBottomLine(out, foreignSize, sentenceNumber, sourceSentence,
				corpus);
		out.println(" \\\\");
		printEndTable(out, caption);
	}

	public static void outputSourceWord(PrintStream out,
			BilingualCorpus corpus, int sentenceNumber, byte sentenceSource,
			int position) throws UnsupportedEncodingException {
		String word = outputLatexString(corpus.getSourceWord(sentenceNumber,
				sentenceSource, position));
		if (corpus.sourceRareWord(corpus.getSourceWordId(sentenceNumber,
				sentenceSource, position))) {
			out.println("\\color{red}{\\alsw{" + word + "}} \\\\");
		} else if (corpus._sourceWordsCounts.get(corpus.getSourceWordId(
				sentenceNumber, sentenceSource, position)) < 10) {
			out.println("\\color{green}{\\alsw{" + word + "}} \\\\");
		} else if (corpus._sourceWordsCounts.get(corpus.getSourceWordId(
				sentenceNumber, sentenceSource, position)) < 20) {
			out.println("\\color{yellow}{\\alsw{" + word + "}}\\\\");
		} else {
			out.println("\\alsw{" + word + "}\\\\");
		}
	}

	public static void printBottomLine(PrintStream out, int len,
			int sentenceNumber, byte sentenceSource, BilingualCorpus corpus)
			throws UnsupportedEncodingException {
		out.print("&");
		for (int i = 0; i < len; i++) {
			String word = outputLatexString(corpus.getForeignWord(
					sentenceNumber, sentenceSource, i));
			if (corpus._foreignWordsCounts.get(corpus.getForeignWordId(
					sentenceNumber, sentenceSource, i)) < 5) {
				out.print("\\albw{\\color{red}{" + word + "}}" + " &");
			} else if (corpus._foreignWordsCounts.get(corpus.getForeignWordId(
					sentenceNumber, sentenceSource, i)) < 10) {
				out.print("\\albw{\\color{green}{" + word + "}}" + " &");
			} else if (corpus._foreignWordsCounts.get(corpus.getForeignWordId(
					sentenceNumber, sentenceSource, i)) < 20) {
				out.print("\\albw{\\color{yellow}{" + word + "}}" + " &");
			} else {
				out.print("\\albw{" + word + "}" + " &");
			}
		}
	}

	public static void printLineWithNumber(PrintStream out, int size) {
		out.print("&");
		for (int i = 0; i < size; i++) {
			out.print("\\aln{" + i + "}" + " & ");
		}
	}

	public static void printBeginTable(PrintStream out, int size) {
		out.println("\\begin{figure}[h]");
		out.println("\\begin{center}");
		out.print("\\begin{tabular}{");
		out.println(" r\\mysep ");
		for (int i = 0; i < size; i++) {
			out.print(" c\\mysep ");
		}
		out.println();
		out.println(" l} ");
	}

	public static void printEndTable(PrintStream out, String caption) {
		out.println("\\end{tabular}");
		out.println("\\end{center}");
		out.println("\\caption{" + caption + "}");
		out.println("\\end{figure}");
	}

	public static void printAlignmentCaption(PrintStream out){
		out.println("\\begin{table} \n" +
		"\\begin{center} \n" +
		"\\begin{tabular}{|c|c|} \n" +
		"\\hline \n" +
		"\\multicolumn{2}{|c|}{Matrix dimensions} \\\\ \n" +
		"\\hline \n" +
		"rows & source words \\\\ \n" +
		"columns & foreign words \\\\ \n" +
		"\\hline \n" +
		"\\multicolumn{2}{|c|}{Word Colors}\\\\ \n" +
		"\\hline \n" +
		"\\color{red}{word} & $5 > $ occurrences \\\\ \n" +
		"\\color{green}{word} & $10 > $ occurrences \\\\ \n" +
		"\\color{yellow}{word} & $20 > $ occurrences \\\\ \n" +
		"word & occurrences  $\\leq 20$ \\\\ \n" +
		"\\hline \n" +
		"\\multicolumn{2}{|c|}{Word to word posterior probabilities $p$}\\\\ \n" +
		"\\hline \n" +
		"\\mycircle{0} & $ 0.01 < $ $p$ \\\\ \n" +
		"\\mycircle{0.5} &  $0.01 \\leq $ $p$  $ <  0.05 $\\\\ \n" +
		"\\mycircle{1} &  $0.05 \\leq $ $p$  $ < 0.1 $\\\\ \n" +
		"\\mycircle{2} &  $0.1 \\leq $ $p$  $ < 0.2 $\\\\ \n" +
		"\\mycircle{3} &  $0.2 \\leq $ $p$  $ < 0.3 $\\\\ \n" +
		"\\mycircle{4} &  $0.3 \\leq $ $p$  $ < 0.4 $\\\\ \n" +
		"\\mycircle{5} &  $0.4 \\leq $ $p$  $ < 0.5 $\\\\ \n" +
		"\\mycircle{6} &  $0.5 \\leq $ $p$  $ < 0.6 $\\\\ \n" +
		"\\mycircle{7} &  $0.6 \\leq $ $p$  $ < 0.7 $\\\\ \n" +
		"\\mycircle{8} &  $0.7 \\leq $ $p$  $ < 0.8 $\\\\ \n" +
		"\\mycircle{9} &  $0.8 \\leq $ $p$  $ < 0.9 $\\\\ \n" +
		"\\mycircle{10} &  $0.9 \\leq $ $p$  $ < 0.95 $\\\\ \n" +
		"\\mycircle{11} & $0.95 \\leq $ $p$\\\\ \n" +
		"\\hline \n" +
		"\\multicolumn{2}{|c|}{Alignment points}\\\\ \n" +
		"\\hline \n" +
		"\\color{red}{\\mycircle{5}} & Predicted point\\\\ \n" +
		"\\mycircle{5} & Not Predicted point\\\\ \n" +
		"\\sale & Sure gold alignment point \\\\ \n" +
		"\\pale & Possible gold alignment point \\\\ \n" +
		"\\hline \n" +
		"\\end{tabular} \n" +
		"\\end{center} \n" +
		"\\caption{Alignment Caption} \n" +
		"\\end{table} \n" +
		"\\clearpage\\pagebreak \n");

		
	}
	
	// Shoudl print latex headers and experiment headers
	
	public static void printBeginBig(PrintStream out) {
		out.println("\\documentclass{a0poster}[10pt] \n \\usepackage{rotating} \n \\usepackage{xcolor} \n  \\usepackage[utf8]{inputenc} \n \\begin{document} \n");
		out.println();
		printWaDef(out);
	}
	public static void printBegin(PrintStream out) {
		out.println("\\documentclass{article}[10pt] \n \\usepackage{rotating} \n \\usepackage{xcolor} \n  \\usepackage[utf8]{inputenc} \n \\begin{document} \n");
		out.println();
		printWaDef(out);
	}
	public static void printWaDef(PrintStream out){
		out.println("\\definecolor{myltblue}{rgb}{0.75,0.75,0.95} \n " +
					"\\definecolor{mydkblue}{rgb}{0.55,0.55,0.95}  \n "+
					"\\definecolor{myltred}{rgb}{1.0,0.3,0}  \n "+
					"\\definecolor{mydkred}{rgb}{1,0.55,0.3}  \n " +
					"\\definecolor{mydkyellow}{rgb}{0.6,0.6,0.9}  \n" +
					"\\definecolor{myltyellow}{rgb}{0.7,0.7,0.99}  \n" +
					"\\setlength{\\fboxrule}{2pt} \n" +
					"\\newcommand{\\mycircle}[1]{{\\makebox(5,5){\\begin{picture}(0,0)(0,0)\\put(0,0){\\circle*{#1}}\\end{picture}}}} \n" +
					"\\newcommand{\\egwf}[1]{\\multicolumn{1}{c}{\\begin{rotate}{-30}{#1}\\end{rotate}} } \n " +
					"\\newcommand{\\egnum}[1]{\\multicolumn{1}{c}{\\textbf{#1}}} \n " +
					"\\newcommand{\\mysep}{@{}} \n " + 
					"\\newcommand{\\epty}{}  \n " +
					"\\newcommand{\\nalf}{\\colorbox{white}{\\color{red}\\mycircle{8}}} \n " + 
					"\\newcommand{\\pale}{\\colorbox{myltyellow}{\\color{myltyellow}{$_\\bullet$}}} \n " +
					"\\newcommand{\\sale}{\\fcolorbox{black}{mydkyellow}{\\color{mydkyellow}{$_\\bullet$}}} \n " +
					"\\newcommand{\\palf}{\\colorbox{myltyellow}{{\\color{red}\\mycircle{8}}}} \n " +
					"\\newcommand{\\salf}{\\fcolorbox{black}{mydkyellow}{\\color{red}\\mycircle{8}}} \n " +
					"\\newcommand{\\ealf}{ \\color{black}\\color{red}\\mycircle{8} } \n " +
					"\\newcommand{\\ealfb}{ \\color{black}$_\\bullet$ } \n " +
					"\\newcommand{\\grow}{\\fcolorbox{black}{orange}{$_\\star$}} \n " +
					"\\newcommand{\\growf}{\\fcolorbox{black}{yellow}{$_\\circ$}} \n " +
					"\\newcommand{\\paler}{\\colorbox{myltred}{\\color{myltblue}{$_\\bullet$}}} \n " +
					"\\newcommand{\\saler}{\\fcolorbox{red}{mydkred}{\\color{mydkblue}{$_\\bullet$}}} \n " +
					"\\newcommand{\\palfr}{\\colorbox{myltred}{{$_\\bullet$}}} \n " +
					"\\newcommand{\\salfr}{\\fcolorbox{red}{mydkred}{$_\\bullet$}} \n " +
					"\\newcommand{\\aln}[1]{\\multicolumn{1}{c}{\\textbf{#1}}} %Alignment top number \n " +
					"\\newcommand{\\albw}[1]{\\multicolumn{1}{c}{\\begin{rotate}{-40}{#1}\\end{rotate}}} %Alignment buttom word \n " +
					"\\newcommand{\\alsw}[1]{#1} %Alignment side word \n " +
					"\\newcommand{\\topw}[1]{\\multicolumn{1}{c}{\\begin{rotate}{45}{#1}\\end{rotate}}} \n " + 
					"\\newcommand{\\mc}[1]{\\multicolumn{1}{c}{#1}} \n " +
					"\\newcommand{\\red}[1]{\\color{red}#1\\color{black}} \n " +
					"\\newcommand{\\nepty}[1]{{\\color{gray}\\mycircle{#1}}}  % empty \n " +
					"\\newcommand{\\nnalf}[1]{\\colorbox{white}{\\color{red}\\mycircle{#1}}}  % Predicted point not aligned \n " +
					"\\newcommand{\\npale}[1]{\\colorbox{myltyellow}{\\color{gray}\\mycircle{#1}}} % possible point not alinged \n " +
					"\\newcommand{\\nsale}[1]{\\fcolorbox{black}{mydkyellow}{\\color{gray}\\mycircle{#1}}} \n " +
					"\\newcommand{\\nsalf}[1]{\\fcolorbox{black}{mydkyellow}{\\color{red}\\mycircle{#1}}} \n " +
					"\\newcommand{\\npalf}[1]{\\colorbox{myltyellow}{\\color{red}\\mycircle{#1}}} %possible aligned full \n " +
					"\\newcommand{\\sure}[2]{\\fcolorbox{black}{mydkyellow}{\\color{#2}\\mycircle{#1}}} % sure aligned full \n "	+	
					"\\newcommand{\\possible}[2]{\\colorbox{myltyellow}{\\color{#2}\\mycircle{#1}}} % possible point not alinged \n " +
					"\\newcommand{\\none}[2] {{\\color{#2}\\mycircle{#1}}}  % empty \n "		
					
					
					);
			
	}

	public static void printEnd(PrintStream out) {
		out.println("\\end{document} \n");
	}

	
}
